package day03.reference;

import day02.LoggerUtils;

import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

// 前面讲的弱、虚引用配合引用队列，目的都是为了找到哪些 java 对象被回收，从而进行对它们关联的资源进行进一步清理
// 为了简化 api 难度，从 java 9 开始引入了 Cleaner 对象



/**
 * 在你提供的代码中，clean 4 没有输出的原因可能与 obj 的生命周期有关。具体来说，obj 是一个强引用，即使你创建了 PhantomReference 指向它，只要 obj 在作用域内，垃圾回收器不会回收它。因此，ref4 不会被添加到引用队列中，清理线程也就不会输出 clean 4。
 资源清理的具体内容
 在你的代码中，PhantomReference 和 ReferenceQueue 主要用于监控对象的回收，并在对象被垃圾回收器回收后执行相应的清理操作。通常，这些清理操作涉及释放与对象关联的资源。以下是一些常见的需要清理的资源类型：
 文件句柄：
 打开的文件句柄需要在对象不再使用时关闭，以防止文件描述符耗尽。
 例如，如果 MyResource 类中打开了一个文件，可以在清理操作中关闭该文件。
 网络连接：
 打开的网络连接需要在对象不再使用时关闭，以防止连接泄漏。
 例如，如果 MyResource 类中建立了网络连接，可以在清理操作中关闭该连接。
 数据库连接：
 打开的数据库连接需要在对象不再使用时关闭，以防止连接池耗尽。
 例如，如果 MyResource 类中建立了数据库连接，可以在清理操作中关闭该连接。
 线程：
 创建的线程需要在对象不再使用时停止，以防止线程泄漏。
 例如，如果 MyResource 类中启动了一个线程，可以在清理操作中停止该线程。
 内存资源：
 分配的内存资源需要在对象不再使用时释放，以防止内存泄漏。
 例如，如果 MyResource 类中分配了大量内存，可以在清理操作中释放这些内存。

 */
public class TestCleaner1 {
    public static void main(String[] args) throws IOException {
        ReferenceQueue<MyResource> queue = new ReferenceQueue<>();

        PhantomReference<MyResource> ref1 = new PhantomReference<>(new MyResource(), queue);
        PhantomReference<MyResource> ref2 = new PhantomReference<>(new MyResource(), queue);
        PhantomReference<MyResource> ref3 = new PhantomReference<>(new MyResource(), queue);
        MyResource obj = new MyResource();
        PhantomReference<MyResource> ref4 = new PhantomReference<>(obj, queue);
        PhantomReference<MyResource> ref5 = new PhantomReference<>(new MyResource(), queue);
        PhantomReference<MyResource> ref6 = new PhantomReference<>(new MyResource(), queue);

        // 启动一个线程来处理引用队列
        Thread cleanerThread = new Thread(() -> {
            while (true) {
                try {
                    PhantomReference<? extends MyResource> ref = (PhantomReference<? extends MyResource>) queue.remove();
                    if (ref == ref1) {
                        LoggerUtils.get().debug("clean 1");
                    } else if (ref == ref2) {
                        LoggerUtils.get().debug("clean 2");
                    } else if (ref == ref3) {
                        LoggerUtils.get().debug("clean 3");
                    } else if (ref == ref4) {
                        LoggerUtils.get().debug("clean 4");
                    } else if (ref == ref5) {
                        LoggerUtils.get().debug("clean 5");
                    } else if (ref == ref6) {
                        LoggerUtils.get().debug("clean 6");
                    }
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        cleanerThread.setDaemon(true);
        cleanerThread.start();

        System.gc();
        System.in.read();
    }

    static class MyResource {

    }
}
